﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;

namespace Puzzles_IQ
{
    public partial class PuzzleBoard : Form
    {
        private bool gamestarted;
        private string timerstr, imgpath;
        private int c; //=complexity
        private DateTime start;
        private PictureBox[] pbArray;
        private Locations loc;
        private Picture pic;
        // used by mouse events
        private bool move; 
        private Point mouseDownPos;
        private PictureBox clickedPb;
        private Music music;
        private TotalScore tscore;

        public PuzzleBoard()
        {
            InitializeComponent();
            SetBackground();
            CreateMenu();
            this.DoubleBuffered = true;
            start = new DateTime();
            timer1.Tick += new EventHandler(timer1_Tick);
            timer1.Interval = 1000;
            //
            c = (int)Complexity.Low; 
            //
            PlayMusic();
            tscore = new TotalScore();
            SetTotalScore();
        }

        #region Initial Settings

        private void SetTotalScore()
        { 
            toolStripStatusLabel_Score.Text = "Total score: " + tscore.Score.ToString();
        }

        private void PlayMusic()
        {
            music = new Music();
            music.PlayMusicFromURL(@"Radio\Kiss FM.m3u".AddApplicationPath());
            kissFMToolStripMenuItem.Checked = true;
        }

        private void SetBackground()
        {
            this.BackgroundImage = Image.FromFile(@"Background\pattern2.png".AddApplicationPath());
            this.BackgroundImageLayout = ImageLayout.Tile;
        }

        private void backgroundColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog MyDialog = new ColorDialog();
            MyDialog.AllowFullOpen = false;
            MyDialog.Color = this.BackColor;
            MyDialog.AllowFullOpen = true;
            if (MyDialog.ShowDialog() == DialogResult.OK)
            {
                menuStrip1.BackColor = MyDialog.Color;
                statusStrip1.BackColor = MyDialog.Color;
            }
        }

        private void CreateMenu()
        {
            MenuHelper col = new MenuHelper();
            foreach (string di in col.GetFolders("Collections".AddApplicationPath()))
            {
                ToolStripMenuItem newToolItem = new ToolStripMenuItem(di.FolderName());
                foreach (string fi in col.GetFiles(di))
                {
                    ToolStripMenuItem newToolSubtem = new ToolStripMenuItem(fi.FileName());
                    newToolSubtem.Tag = fi;
                    newToolSubtem.Click += newToolSubtem_Click;
                    newToolItem.DropDownItems.Add(newToolSubtem);
                }
                collectionsToolStripMenuItem.DropDownItems.Add(newToolItem);
            }
        }

        #endregion

        #region Open Image

        // event for dynamically-created collections
        void newToolSubtem_Click(object sender, EventArgs e)
        {
            imgpath = (sender as ToolStripMenuItem).Tag.ToString();
            FillPictureBoxes(imgpath, this.c);
            showInfo();
            gamestarted = false;
            timer1.Stop();
        }

        private void fromImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            openFileDialog1.Filter = "All files (*.*)|*.*|All image files (*.jpeg,*.jpg,*.png,*.bmp)|*.jpeg;*.jpg;*.png;*.bmp";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    timer1.Stop();
                    imgpath = openFileDialog1.FileName;
                    FillPictureBoxes(imgpath, this.c);
                    showInfo();
                }
                catch (System.OutOfMemoryException)
                {
                    MessageBox.Show("Seems like it is something wrong with your file. Please try another one");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error occured {0}. Please try one more time or restart the app.", ex.Message);
                }
            }
        }

        private void fromSamplesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MenuHelper mh = new MenuHelper();
            timer1.Stop();
            imgpath = mh.GetRandomSample();
            FillPictureBoxes(imgpath, this.c);
            showInfo();
            gamestarted = false;
        }

        #endregion

        #region Complexity

        private void x3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.c = Convert.ToInt32((sender as ToolStripItem).Tag);
            // uncheck all
            foreach (ToolStripMenuItem ts in complexityToolStripMenuItem.DropDownItems)
            {
                ts.Checked = false;
            }

            // check clicked
            (sender as ToolStripMenuItem).Checked = true;
            
            switch (c)
            {
                case 3: this.Width = 1100; break;
                case 5: this.Width = 1200; break;
                case 7: this.Width = 1250; break;
                case 10: this.Width = 1360; break;
            }
            timer1.Stop();
            gamestarted = false;

            if (pbArray != null)
            {
                FillPictureBoxes(imgpath, c);
            }
        }

        #endregion

        #region Start & Reset Game

        private void sTARTToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (pbArray == null)
                MessageBox.Show("Please go to Collections and select desired picture");
            else
            {
                loc.MixPoints();

                var pbloc = from l in loc.Move(Direction.Right)
                            select l;

                for (int i = 0; i < pbArray.Length; i++)
                {
                    pbArray[i].Location = pbloc.ToList()[i];
                }
                start = DateTime.Now;
                timer1.Start();
                gamestarted = true;
            }
        }

        private void FillPictureBoxes(string s, int c)
        {
            if (pbArray != null)
                ResetParameters();

            pbArray = new PictureBox[c * c];
            pic = new Picture(Image.FromFile(s), (Complexity)c);
            loc = new Locations(pic.blockSize, (Complexity)c);

            var pbloc = from l in loc.SetInitialPoints()
                        select l;
            var pbim = from i in pic.SliceImage()
                       select i;
            pbloc.ToList();
            pbim.ToList();

            for (int x = 0; x < pbArray.Length; x++)
            {
                pbArray[x] = new PictureBox();
                pbArray[x].Size = pic.blockSize;
                pbArray[x].Image = pbim.ToList()[x];
                pbArray[x].Location = pbloc.ToList()[x];
                pbArray[x].Name = x.ToString();
                pbArray[x].MouseDown += new MouseEventHandler(PictureBox_MouseDown);
                pbArray[x].MouseMove += new MouseEventHandler(PictureBox_MouseMove);
                pbArray[x].MouseUp += new MouseEventHandler(PictureBox_MouseUp);
                this.Controls.Add(pbArray[x]);
            }
        }

        private void ResetParameters()
        {
            for (int i = 0; i < pbArray.Length; i++)
            {
                this.Controls.Remove(pbArray[i]);
            }
        }

        private String PuzzleComlplete()
        {
            timer1.Stop();
            return timerstr.Remove(8);
        }

        #endregion

        #region Mouse Events

        private void PictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (gamestarted)
            {
                move = true;
                clickedPb = sender as PictureBox;
                mouseDownPos = e.Location;
            }
        }

        private void PictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (move && gamestarted)
            {
                clickedPb.BringToFront();
                clickedPb.Left = e.X + clickedPb.Left - mouseDownPos.X;
                clickedPb.Top = e.Y + clickedPb.Top - mouseDownPos.Y;
            }
        }

        // checks cell, checks winner, notifies score, notifies time
        private void PictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (gamestarted)
            {
                Sound sound = new Sound();
                move = false;
                
                var pblocs = from p in pbArray
                             select p.Location;

                if (loc.IsFreePlace(clickedPb.Location, clickedPb.Size, pblocs.ToList()))
                {
                    sound.PutPuzzle();
                    clickedPb.Location = loc.potentialLocation;
                    tscore.AddScore(3);
                    SetTotalScore();
                }

                // WINNER?
                if (loc.IsWinner(pblocs.ToList()))
                {
                    tscore.AddScore(19);
                    SetTotalScore();
                    tscore.Save();
                    sound.Win();
                    MessageBox.Show("Congrats!!! You WIN!" + "\nScore: " + tscore.Score + "\nTime: " + PuzzleComlplete());
                    gamestarted = false;
                }
            }
        }

        #endregion

        #region InformationPanel

        private void showInfo()
        {
            InformationHelper ih = new InformationHelper();
            pictureBox1.Image = pic.GetSmallPicture(imgpath);
            richTextBox1.LoadFile(ih.LoadImgDescription(imgpath));
        }

        #endregion

        #region Volume & Music

        private void kissFMToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem t in toolStripSplitButton1.DropDownItems)
            {
                t.Checked = false;
            }
            music.PlayMusicFromURL((@"Radio\" + sender.ToString() + ".m3u").AddApplicationPath());
            (sender as ToolStripMenuItem).Checked = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            music.PlayerStop();
        }

        private void button_volume_down_Click(object sender, EventArgs e)
        {
            switch ((sender as Button).Name)
            {
                case "button_volume_up": music.ChangePlayerVolume(5); break;
                case "button_volume_down": music.ChangePlayerVolume(-5); break;
            }
        }

        #endregion

        #region Timer

        private void timer1_Tick(object sender, EventArgs e)
        {
            timerstr = (DateTime.Now - start).ToString();
            toolStripStatusLabel_Timer.Text = "Game timer: " + timerstr.Remove(8);
        }

        #endregion

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

    }
}
